package com.br.aiops.alert;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.br.aiops.alert.config.ReceiverCache;
import com.br.aiops.counter.AlertLogCounter;
import com.br.aiops.counter.Counter;
import com.br.aiops.rule.Rule;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class AlertSender {
    private static final Logger LOGGER = LoggerFactory.getLogger(AlertSender.class);

    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final String CODE = "code";

    @Autowired
    private AlertData alertData;

    @Autowired
    private ReceiverCache receiverCache;

    @Autowired
    private Counter counter;

    @Autowired
    private K8sUtils k8sUtils;

    @Value("${env.cluster}")
    private String cluster;
    @Value("${env.sub-cluster}")
    private String subCluster;
    @Value("${env.sub-cluster-name}")
    private String subClusterName;
    @Value("${alarm.url}")
    private String alarmUrl;


    public void sendAlertMessage(AlertLogCounter alertLogCounter) {
        try {
            //设置已经发送过告警
            counter.getCounter().get(alertLogCounter.counterKey()).setAlerted(true);

            JSONArray allPods = getAllPods(alertLogCounter);
            LOGGER.info("service {} 获取了pod数据：{}.", alertLogCounter.getAlertLog().getService(), allPods);
            alertLogCounter.setAllPods(allPods);

            String body = alertData.buildAlertDataJSONString(alertLogCounter);
            LOGGER.info("发送告警:{}", body);

            send(body);
        } catch (Exception e) {
            LOGGER.error("发送告警失败。", e);
        }
    }

    private JSONArray getAllPods(AlertLogCounter alertLogCounter) {
        //设置告警的pod总数
        if (Objects.equals(alertLogCounter.getAlertLog().getSubEnv(), subClusterName)) {
            //请求子环境
            return k8sUtils.getPods(subCluster, alertLogCounter.getAlertLog().getService());
        }

        return k8sUtils.getPods(cluster, alertLogCounter.getAlertLog().getService());
    }

    public void sendResumeMessage(AlertLogCounter alertLogCounter) {
        try {
            //判断是否发送过告警，没有发送过告警，则不发送恢复告警
            AlertLogCounter logCounter = counter.getCounter().get(alertLogCounter.counterKey());
            //没有设置过发送状态；或者状态为false，则不发送恢复
            if (Objects.isNull(logCounter.getAlerted()) || !logCounter.getAlerted()) {
                LOGGER.info("该AlertLogCounter {} 未发送过告警，将不发送恢复告警；", alertLogCounter.counterKey());
                return;
            }

            //设置告警的pod总数
            JSONArray allPods = k8sUtils.getPods(cluster, alertLogCounter.getAlertLog().getService());
            alertLogCounter.setAllPods(allPods);

            String body = alertData.buildResumeAlertDataJSONString(alertLogCounter);
            LOGGER.info("发送恢复告警:{}", body);
            send(body);
        } catch (Exception e) {
            LOGGER.error("发送告警失败。", e);
        }
    }

    public void sendConfigErrorAlertMessage(Rule rule, String message) {
        try {
            AlertLogCounter mock = AlertLogCounter.builder().alertTimesInAllCycle(new AtomicInteger(1)).rule(rule).build();
            String body = alertData.buildLogAlertConfigErrorJSONString(mock, message);
            LOGGER.info("发送告警:{}", body);
            send(body);
        } catch (Exception e) {
            LOGGER.error("发送告警失败。", e);
        }
    }

    private void send(String body) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(5, TimeUnit.SECONDS)
                .callTimeout(5, TimeUnit.SECONDS)
                .readTimeout(5, TimeUnit.SECONDS)
                .writeTimeout(5, TimeUnit.SECONDS)
                .build();

        RequestBody requestBody = RequestBody.create(body, JSON);

        Request request = new Request.Builder()
                .url(alarmUrl)
                .post(requestBody).build();
        try {
            Response response = client.newCall(request).execute();
            if (Objects.equals(response.code(), 200)) {
                String respBody = response.body().string();
                JSONObject bodyJson = JSONObject.parseObject(respBody);
                boolean success = Objects.nonNull(bodyJson) && Objects.equals(bodyJson.getString(CODE), "1000");
                if (!success) {
                    LOGGER.error("发送告警失败, 返回结果为：{}。", respBody);
                }
            }
        } catch (Exception e) {
            LOGGER.error("发送告警失败！", e);
        }
    }
}
